﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;
using AutoMapper.QueryableExtensions;
using Jy.Abp.Application;
using Jy.Abp.Extensions;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Auditing;
using Volo.Abp.Linq;
using Volo.Abp.ObjectMapping;

namespace Jy.Abp.Extensions;

public static class IQueryableExtensions
{
    /// <summary>
    /// 排序（如果指定了排序）
    /// </summary>
    public static IQueryable<T> SortBy<T>(this IQueryable<T> query, PagedAndSortedFilter filter)
    {
        if (filter.Sorting.HasValue())
            return query.OrderBy($"{filter.Sorting}");
        if (typeof(T).IsAssignableTo<IHasCreationTime>())
            return query.OrderByDescending(e => ((IHasCreationTime)e).CreationTime);
        throw new UserFriendlyException("未指定排序，但此查询需要排序!");
    }
    /// <summary>
    /// 使用指定的filter分页
    /// </summary>
    public static IQueryable<T> PageBy<T>(this IQueryable<T> query, PagedAndSortedFilter filter)
    {
        return query.Skip(filter.SkipCount).Take(filter.MaxResultCount);
    }
    /// <summary>
    /// 使用指定的filter分页并排序（如果指定了排序）
    /// </summary>
    public static IQueryable<T> PageAndSortBy<T>(this IQueryable<T> query, PagedAndSortedFilter filter)
    {
        return query.SortBy(filter).PageBy(filter);
    }

    public static IQueryable<T> ProjectTo<T>(this IQueryable query, IObjectMapper objectMapper)
    {
        return query.ProjectTo<T>(objectMapper.GetMapper().ConfigurationProvider);
    }

    public static async Task<TPagedResultDto> ToPagedListAsync<T, TPagedResultDto>(
        this IQueryable<T> query,
        IAsyncQueryableExecuter queryableExecuter,
        PagedAndSortedFilter filter)
        where TPagedResultDto : PagedResultDto<T>, new()
    {
        var totalCcount = await queryableExecuter.CountAsync(query);
        var items = await queryableExecuter.ToListAsync(query.PageAndSortBy(filter));

        return new TPagedResultDto
        {
            Items = items,
            TotalCount = totalCcount
        };
    }

    public static async Task<PagedResultDto<T>> ToPagedListAsync<T>(
        this IQueryable<T> query,
        IAsyncQueryableExecuter queryableExecuter,
        PagedAndSortedFilter filter)
    {
        var totalCcount = await queryableExecuter.CountAsync(query);
        var items = await queryableExecuter.ToListAsync(query.PageAndSortBy(filter));

        return new PagedResultDto<T>
        {
            Items = items,
            TotalCount = totalCcount
        };
    }

    public static async Task<List<T>> ToListAsync<T>(
        this IQueryable<T> query,
        IAsyncQueryableExecuter queryableExecuter)
    {
        return await queryableExecuter.ToListAsync(query);
    }

    public static async Task<T[]> ToArrayAsync<T>(
        this IQueryable<T> query,
        IAsyncQueryableExecuter queryableExecuter)
    {
        return await queryableExecuter.ToArrayAsync(query);
    }

    public static async Task<int> CountAsync<T>(
       this IQueryable<T> query,
       IAsyncQueryableExecuter queryableExecuter)
    {
        return await queryableExecuter.CountAsync(query);
    }
}

